﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Web.WebPages;
using LX.Core.Model;

namespace LX.Web.Mvc
{
    public class TreeView<T> 
    {
        public TreeView(List<T> data)
        {
            Data = data;
            ItemFormat = t => "<li><a tname=\"name\" tvalue=\"value\">value</a>{0}</li>";
            ContainerFormat = t => "<ul>{0}</ul>";
            RootContainerFormat = "<ul class=\"tree treeFolder  expand\">{0}</ul>";
        }


        /// <summary>
        /// 数据源
        /// </summary>
        public List<T> Data { get; set; }

        /// <summary>
        /// 选择根节点
        /// </summary>
        public Func<T, bool> RootChooser { get; set; }

        /// <summary>
        /// 选择子节点
        /// </summary>
        public Func<T, List<T>, List<T>> ChildChooser { get; set; }

        public Func<T, String> ItemFormat { get; set; }

        public Func<T, String> ContainerFormat { get; set; }

        public string RootContainerFormat { get; set; }

        public TreeView<T> FormatItem(Func<T, String> fn)
        {
            ItemFormat = fn;
            return this;
        }

        public TreeView<T> ChooseRoot(Func<T, bool> fn)
        {
            RootChooser = fn;
            return this;
        }

        public TreeView<T> ChooseChildren(Func<T, List<T>, List<T>> fn)
        {
            ChildChooser = fn;
            return this;
        }

        public TreeView<T> FormatContainer(Func<T, String> fn)
        {
            ContainerFormat = fn;
            return this;
        }

        public TreeView<T> FormatRootContainer(string format)
        {
            RootContainerFormat = format;
            return this;
        }

        public IHtmlString  Render()
        {
            var builder = new StringBuilder();
            var rootnodes = Data.Where(RootChooser);
            foreach (var node in rootnodes)
            {
                appendnode(builder, node);
            }
            string html = string.Format(RootContainerFormat, builder);
            return new HtmlString(html);   
        }

        private void appendnode(StringBuilder sb, T item)
        {
            var itemstring = ItemFormat(item);
            string container = "";
            var children =ChildChooser(item, this.Data);
            if (children.Count() > 0)
            {
                var sbnode = new StringBuilder();
                container = ContainerFormat(item);
                foreach (var child in children)
                {
                    appendnode(sbnode, child);
                }
                container = string.Format(container, sbnode.ToString());
            }
            itemstring = string.Format(itemstring, container);
            sb.Append(itemstring);
        }
    }
}
